package com.iflytek.uoamp.agent.monitor.mcagent;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.quartz.JobKey;

import com.alibaba.fastjson.JSON;
import com.iflytek.uoamp.agent.core.sender.monitorsender.monitorinterface.IItem;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.MonitorItemConfig;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.MonitorItemResult;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.MonitorPluginType;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.SendResponse;
import com.iflytek.uoamp.agent.core.sender.monitorsender.requestObj.SendResponse.RESPONSESTATUS;
import com.iflytek.uoamp.agent.monitor.job.JobResult;
import com.iflytek.uoamp.agent.monitor.job.MCAgentJobManager;

/**
 * 
 * @ClassName: MonitorResultSender
 * @Description: monitor发送结果类
 * @author qinanyuan
 * @date 2017年3月23日 下午3:22:37
 */
public class MonitorResultSender implements Runnable {
	
	private static MonitorResultSender instance = new MonitorResultSender();
	private final byte[] lock = new byte[0];
	private final List<JobResult> jobResult;

	/**
	 * sendMonitorResults to mc server
	 * */
	private static SendResponse sendMonitorResults(List<MonitorItemResult> monitorResults,String configs) {
		if (monitorResults==null || monitorResults.isEmpty()) {
			Logger.getRootLogger().info("ServerMonitorJob sendMonitorResults  monitor Services results is empty");
			return null;
		}

		Logger.getRootLogger().info("ServerMonitorJob sendMonitorResults sends " + monitorResults.size() + " monitor results");
//		Logger.getRootLogger().info("ServerMonitorJob sendMonitorResults 结果集合==============> " + JSON.toJSONString(monitorResults));
		try {
			
			List<IItem> sendObjs = new LinkedList<IItem>();
			
			for(MonitorItemResult cur:monitorResults){
				cur.getHeader().put("configs", configs);
				sendObjs.add(cur);
			}
			if(MCAgentMain.getSenderClient().getConfig().isUseHttp()){
				Object result = MCAgentMain.getSenderClient().sendBatchByHttp(sendObjs);
				SendResponse jsonObject = JSON.parseObject(result.toString(), SendResponse.class);
				return jsonObject;
			}else{
				Object result =  MCAgentMain.getSenderClient().sendBatchBySafe(sendObjs);
//				Logger.getRootLogger().info("SendBatchBySafe 入参==============> " + JSON.toJSONString(sendObjs)+"    出参==============>"+JSON.toJSONString(result));
				if(result!=null && result instanceof SendResponse){
					return (SendResponse)result;
				}
			}
			return null;
		} catch (Exception e) {
			Logger.getRootLogger().error("ServerMonitorJob sendMonitorResults send monitor results failed, throw exception:" + e.toString(),e);
			// save unsend data to log file
			for (MonitorItemResult result : monitorResults) {
				Logger.getRootLogger().error("ServerMonitorJob sendMonitorResults send failed Data: " + result.toString());
			}
		}
		return null;
	}
	
	/**
	 * get update list 
	 * */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static List<MonitorItemConfig> getNeedUpdateJob(String type,List<String> updateNameList) {
		if (updateNameList == null || updateNameList.isEmpty()) {
			Logger.getRootLogger().info("ServerMonitorJob updateJobItem name list needed to update is null or empty");
			return new LinkedList<MonitorItemConfig>();
		}
		MonitorPluginType itemPluginType = new MonitorPluginType(MCAgentConfig.getInstance().getMonitoredPointIp(), type ,updateNameList);
		try {
			Object result = null;
			if(MCAgentMain.getSenderClient().getConfig().isUseHttp()){
				result = MCAgentMain.getSenderClient().sendByHttp(itemPluginType);
				List list = JSON.parseObject(result.toString(), List.class);
				List<MonitorItemConfig> monitorItems = new LinkedList<MonitorItemConfig>();
				for(Object cur:list){
					monitorItems.add(JSON.parseObject(cur.toString(), MonitorItemConfig.class));
				}
				return monitorItems;
			}else{
				result = MCAgentMain.getSenderClient().sendBySafe(itemPluginType);
				if (!(result instanceof List)) {
					return null;
				}
				return (List<MonitorItemConfig>) result;
			}

		} catch (Exception e) {
			Logger.getRootLogger().error("updateNormalMonitorJob   getMonitorItem failed",e);
			return null;
		}
	}
	
	private MonitorResultSender(){
		this.jobResult = new LinkedList<JobResult>();
	}
	
	public static List<MonitorItemConfig> sendMonitorInfo(List<MonitorItemResult> monitorResults,String configs,String type){
		SendResponse response = sendMonitorResults(monitorResults,configs);
		List<MonitorItemConfig> updateList = null;
		if (response == null || response.getStatus() == RESPONSESTATUS.ERROR) {
			Logger.getRootLogger().error("ServerMonitorJob sendMonitorResults  send monitor failed" + (response != null ? "" : ",response is null"));
			for (MonitorItemResult result : monitorResults) {
				Logger.getRootLogger().error("ServerMonitorJob sendMonitorResults   send failed Data: " + result.toString());
			}
			return null;
		} else {
			Logger.getRootLogger().info("ServerMonitorJob sendMonitorResults   send monitor responses " + response.getStatus());
			// update monitor info
			if (response.getStatus() == RESPONSESTATUS.UPDATE) {
				updateList =  getNeedUpdateJob(type,response.getUpdateList());
			}
			return updateList;
		}
	}
	
	public static MonitorResultSender getInstance(){
		return instance;
	}
	
	public void addMonitorResult(JobKey jobKey,List<MonitorItemResult> monitorResults){
		synchronized (lock) {
			jobResult.add(new JobResult(jobKey, monitorResults));
			lock.notifyAll();
		}
	}
	
	@Override
	public void run() {
		Logger.getRootLogger().info("start MonitorResultSender Thread...");
		List<JobResult> clone = new LinkedList<JobResult>();
		while(true){
			
			//如何应对没有监控项目的情况,如果不更新agent,则继续坚持本主机的监控项配置
//			Logger.getRootLogger().info("**********isStartAgent:" + MCAgentMain.isStartAgent());
//			Logger.getRootLogger().info("**********isStartMonitor:" + MCAgentMain.isStartMonitor());
			if(MCAgentMain.isStartAgent() && !MCAgentMain.isStartMonitor()){
				try {
					List<MonitorItemConfig> monitorList = MCAgentMain.initMonitorData();
					if (monitorList != null && monitorList.size() > 0) {
						for (MonitorItemConfig cur : monitorList){
							MCAgentMain.getCheckNames().add(cur.getServerDesc());
						}
						MCAgentJobManager.startJob(monitorList);
						MCAgentMain.setStartMonitor(true);
//						Logger.getRootLogger().info("**********StartMonitor is true!");
					}
				} catch (Exception e) {
					Logger.getRootLogger().error(e.getMessage(),e);
				}
			}
			
			try {
				synchronized (lock) {
					if (jobResult.isEmpty()) {
						lock.wait(30 * 1000);
//						Logger.getRootLogger().info("**********jobResult is empty!");
//						Logger.getRootLogger().info("**********SchedulerMonitorMap:" + JSON.toJSONString(MCAgentJobManager.getSchedulerMonitorMap()));
						//没有监控项启动需要从服务端重新获取
						if(MCAgentJobManager.getSchedulerMonitorMap().isEmpty()){
							Logger.getRootLogger().info("**********SchedulerMonitorMap is empty!");
						    MCAgentMain.setStartMonitor(false);
						}
					}
					clone.addAll(jobResult);
					jobResult.clear();
				}
			} catch (Exception e) {
				Logger.getRootLogger().error("jobResult lock has encountered a interruptedException", e);
			}
			
			if (clone.isEmpty()) {
				continue;
			}
			Logger.getRootLogger().info("get jobResult size : " + clone.size());
			
			try{
				for(JobResult cur:clone){
					List<MonitorItemConfig>  updateList = sendMonitorInfo(cur.getMonitorResults(),MCAgentMain.setToString(),"checklocal");
					
					Set<String> uplist = new HashSet<String>();
					if (updateList != null && !updateList.isEmpty()) {
						MCAgentJobManager.updateJobSchedular(cur.getKey(), updateList);
						for(MonitorItemConfig config:updateList){
							uplist.add(config.getServerDesc());
						}
					}
					MCAgentJobManager.parseResultAndReSchedularJob(cur.getKey(),cur.getMonitorResults(), uplist);
				}
			} catch(Exception e){
				Logger.getRootLogger().error(e.getMessage(),e);
			} finally {
				clone.clear();
			}
		}
	}
	
}
